/*
@Author   : Uyynot
@Email    : uyynot@qq.com
@Time     : 2024/1/12 15:44
@File     : config.go
@Project  : gohub
@Desc     :
*/
package config

import (
	"github.com/spf13/cast"
	"github.com/spf13/viper"
	"gohub/pkg/helpers"
	"os"
)

// viper实例
var vp *viper.Viper

// ConfigFunc 动态加载配置信息
type ConfigFunc func() map[string]any

// 将环境变量加载到该map；loadConfig再动态生成配置信息
var ConfigFuncs map[string]ConfigFunc

func init() {
	//1 初始化viper库
	vp = viper.New()
	//2 配置文件类型
	vp.SetConfigType("env")
	//3 环境变量配置文件查找路径(相对于main.go)
	vp.AddConfigPath(".")
	//4 设置环境变量前缀(以区分Go的系统环境变量)
	vp.SetEnvPrefix("appenv")
	//5 读取环境变量(支持flags)
	vp.AutomaticEnv()

	//初始化动态配置map映射
	ConfigFuncs = make(map[string]ConfigFunc)
}

// 加载环境变量
func loadEnv(envSuffix string) {
	//默认读取.env文件，如果有传参 --env=name的话则读取.env.name文件
	envPath := ".env"
	if len(envSuffix) > 0 {
		filePath := ".env." + envSuffix
		//如果用户动态传入的配置文件存在，则读取该配置文件
		if _, err := os.Stat(filePath); err == nil {
			envPath = filePath
		}
	}

	//加载env配置文件
	vp.SetConfigName(envPath)
	//读取不到配置文件，直接报错
	if err := vp.ReadInConfig(); err != nil {
		panic(err)
	}

	//监控env配置文件，有变动则重新加载
	vp.WatchConfig()
}

// 注册配置信息
func loadConfig() {
	for name, fn := range ConfigFuncs {
		vp.Set(name, fn())
	}
}

func InitConfig(env string) {
	//加载环境配置变量
	loadEnv(env)
	//注册配置信息
	loadConfig()
}

func internalGet(path string, defaultValue ...any) any {
	//config或环境变量不存在
	if !vp.IsSet(path) || helpers.Empty(vp.Get(path)) {
		if len(defaultValue) > 0 {
			return defaultValue[0]
		}
		return nil
	}
	return vp.Get(path)
}

// Env 读取环境变量，支持默认值
func Env(envname string, defaultValue ...any) any {
	if len(defaultValue) > 0 {
		return internalGet(envname, defaultValue[0])
	}
	return internalGet(envname)
}

// Add 新增配置项
func Add(name string, configFn ConfigFunc) {
	ConfigFuncs[name] = configFn
}

// GetString 获取stging类型的配置信息
func GetString(path string, defaultValue ...any) string {
	return cast.ToString(internalGet(path, defaultValue...))
}

// GetInt 获取int类型的配置信息
func GetInt(path string, defaultValue ...any) int {
	return cast.ToInt(internalGet(path, defaultValue...))
}

// GetFloat64 获取 float64 类型的配置信息
func GetFloat64(path string, defaultValue ...interface{}) float64 {
	return cast.ToFloat64(internalGet(path, defaultValue...))
}

// GetInt64 获取 Int64 类型的配置信息
func GetInt64(path string, defaultValue ...interface{}) int64 {
	return cast.ToInt64(internalGet(path, defaultValue...))
}

// GetUint 获取 Uint 类型的配置信息
func GetUint(path string, defaultValue ...interface{}) uint {
	return cast.ToUint(internalGet(path, defaultValue...))
}

// GetBool 获取bool类型的配置信息
func GetBool(path string, defaultValue ...any) bool {
	return cast.ToBool(path)
}

// GetStringMapString 获取结构数据
func GetStringMapString(path string) map[string]string {
	return vp.GetStringMapString(path)
}

// Get 获取配置项
func Get(path string, defaultValue ...any) string {
	return GetString(path, defaultValue...)
}
